-- Lua Battle System - 战斗计算器

local Logger = require("utils.logger")
local BattleConfig = require("config.battle_config")
local Random = require("utils.random")

local CombatCalculator = {
    -- 伤害类型
    damage_types = {
        PHYSICAL = "physical",
        MAGIC = "magic",
        TRUE = "true"
    },
    
    -- 伤害公式
    damage_formulas = {
        physical = "(attack - defense) * 0.5 + 1",
        magic = "(magic_attack - magic_defense) * 0.5 + 1",
        ["true"] = "base_damage"
    }
}

-- 战斗计算器构造函数
function CombatCalculator:new()
    local o = {}
    setmetatable(o, self)
    self.__index = self
    return o
end

-- 计算伤害
function CombatCalculator:calculate_damage(attacker, defender, skill)
    local damage_type = skill.type or self.damage_types.PHYSICAL
    local damage = 0
    
    -- 获取攻击者和防御者的当前属性
    local attacker_stats = attacker:get_current_stats()
    local defender_stats = defender:get_current_stats()
    
    -- 根据伤害类型计算基础伤害
    if damage_type == self.damage_types.PHYSICAL then
        damage = self:calculate_physical_damage(attacker_stats, defender_stats, skill)
    elseif damage_type == self.damage_types.MAGIC then
        damage = self:calculate_magic_damage(attacker_stats, defender_stats, skill)
    elseif damage_type == self.damage_types.TRUE then
        damage = self:calculate_true_damage(attacker_stats, defender_stats, skill)
    end
    
    -- 应用伤害浮动
    damage = self:apply_damage_variance(damage, skill)
    
    -- 检查是否暴击
    local is_critical = self:check_critical(attacker_stats, skill)
    if is_critical then
        damage = self:apply_critical_damage(damage, skill)
    end
    
    -- 检查是否命中
    local is_hit = self:check_hit(attacker_stats, defender_stats, skill)
    if not is_hit then
        return 0, false, false -- 未命中
    end
    
    -- 确保伤害至少为1
    damage = math.max(1, damage)
    
    return damage, is_critical, is_hit
end

-- 计算物理伤害
function CombatCalculator:calculate_physical_damage(attacker_stats, defender_stats, skill)
    local damage = 0
    
    -- 基础伤害公式：(攻击 - 防御) * 0.5 + 1
    damage = (attacker_stats.attack - defender_stats.defense) * 0.5 + 1
    
    -- 应用技能伤害加成
    damage = damage * skill.damage.multiplier + skill.damage.base
    
    -- 应用穿透效果
    if skill.effects.penetration > 0 then
        damage = damage + defender_stats.defense * skill.effects.penetration
    end
    
    return damage
end

-- 计算魔法伤害
function CombatCalculator:calculate_magic_damage(attacker_stats, defender_stats, skill)
    local damage = 0
    
    -- 基础伤害公式：(魔法攻击 - 魔法防御) * 0.5 + 1
    damage = (attacker_stats.magic_attack - defender_stats.magic_defense) * 0.5 + 1
    
    -- 应用技能伤害加成
    damage = damage * skill.damage.multiplier + skill.damage.base
    
    -- 应用穿透效果
    if skill.effects.penetration > 0 then
        damage = damage + defender_stats.magic_defense * skill.effects.penetration
    end
    
    return damage
end

-- 计算真实伤害
function CombatCalculator:calculate_true_damage(attacker_stats, defender_stats, skill)
    -- 真实伤害忽略防御
    local damage = skill.damage.base + attacker_stats.attack * skill.damage.multiplier
    return damage
end

-- 应用伤害浮动
function CombatCalculator:apply_damage_variance(damage, skill)
    local variance = skill.damage.variance or BattleConfig.damage_calculation.damage_variance
    local min_damage = damage * (1 - variance)
    local max_damage = damage * (1 + variance)
    
    return Random:float(min_damage, max_damage)
end

-- 检查是否暴击
function CombatCalculator:check_critical(attacker_stats, skill)
    local crit_chance = BattleConfig.damage_calculation.critical_chance
    
    -- 应用技能暴击率加成
    if skill.effects.crit_chance then
        crit_chance = crit_chance + skill.effects.crit_chance
    end
    
    -- 应用攻击者幸运值加成
    crit_chance = crit_chance + attacker_stats.luck * 0.01
    
    -- 确保暴击率在合理范围内
    crit_chance = math.min(crit_chance, 0.95) -- 最大95%暴击率
    crit_chance = math.max(crit_chance, 0.01) -- 最小1%暴击率
    
    return Random:bool(crit_chance)
end

-- 应用暴击伤害
function CombatCalculator:apply_critical_damage(damage, skill)
    local crit_multiplier = BattleConfig.damage_calculation.critical_multiplier
    
    -- 应用技能暴击伤害加成
    if skill.effects.crit_multiplier then
        crit_multiplier = crit_multiplier + skill.effects.crit_multiplier
    end
    
    return damage * crit_multiplier
end

-- 检查是否命中
function CombatCalculator:check_hit(attacker_stats, defender_stats, skill)
    local accuracy = skill.effects.accuracy or 1.0
    local evasion = defender_stats.luck * 0.01 -- 闪避率基于幸运值
    
    -- 计算最终命中率
    local hit_chance = accuracy - evasion
    hit_chance = math.min(hit_chance, 0.99) -- 最大99%命中率
    hit_chance = math.max(hit_chance, 0.01) -- 最小1%命中率
    
    return Random:bool(hit_chance)
end

-- 计算治疗量
function CombatCalculator:calculate_healing(caster, target, skill)
    local healing = 0
    
    -- 获取施法者的当前属性
    local caster_stats = caster:get_current_stats()
    
    -- 基础治疗公式：魔法攻击 * 治疗系数 + 基础治疗量
    healing = caster_stats.magic_attack * skill.healing.multiplier + skill.healing.base
    
    -- 应用治疗浮动
    healing = self:apply_healing_variance(healing, skill)
    
    return healing
end

-- 应用治疗浮动
function CombatCalculator:apply_healing_variance(healing, skill)
    local variance = skill.healing.variance or BattleConfig.damage_calculation.damage_variance
    local min_healing = healing * (1 - variance)
    local max_healing = healing * (1 + variance)
    
    return Random:float(min_healing, max_healing)
end

-- 计算状态效果命中概率
function CombatCalculator:calculate_status_effect_chance(caster, target, effect_info)
    local base_chance = effect_info.chance or 1.0
    local caster_stats = caster:get_current_stats()
    local target_stats = target:get_current_stats()
    
    -- 应用施法者幸运值加成
    local chance = base_chance + caster_stats.luck * 0.01
    
    -- 应用目标幸运值减免
    chance = chance - target_stats.luck * 0.01
    
    -- 确保概率在合理范围内
    chance = math.min(chance, 0.95) -- 最大95%概率
    chance = math.max(chance, 0.05) -- 最小5%概率
    
    return chance
end

-- 计算行动速度
function CombatCalculator:calculate_action_speed(character)
    local stats = character:get_current_stats()
    local speed = stats.speed
    
    -- 应用随机浮动
    speed = speed + Random:int(-5, 5)
    
    return speed
end

-- 计算闪避概率
function CombatCalculator:calculate_evasion(character)
    local stats = character:get_current_stats()
    local evasion = stats.luck * 0.01
    
    return evasion
end

-- 计算格挡概率
function CombatCalculator:calculate_block_chance(character)
    local stats = character:get_current_stats()
    local block_chance = stats.defense * 0.005
    
    -- 确保格挡率在合理范围内
    block_chance = math.min(block_chance, 0.5) -- 最大50%格挡率
    block_chance = math.max(block_chance, 0) -- 最小0%格挡率
    
    return block_chance
end

-- 计算格挡减伤
function CombatCalculator:calculate_block_reduction(character)
    local stats = character:get_current_stats()
    local reduction = stats.defense * 0.01
    
    -- 确保减伤在合理范围内
    reduction = math.min(reduction, 0.75) -- 最大75%减伤
    reduction = math.max(reduction, 0) -- 最小0%减伤
    
    return reduction
end

-- 计算暴击抵抗
function CombatCalculator:calculate_crit_resistance(character)
    local stats = character:get_current_stats()
    local resistance = stats.luck * 0.01
    
    -- 确保暴击抵抗在合理范围内
    resistance = math.min(resistance, 0.5) -- 最大50%暴击抵抗
    resistance = math.max(resistance, 0) -- 最小0%暴击抵抗
    
    return resistance
end

-- 计算经验值奖励
function CombatCalculator:calculate_exp_reward(attacker, defender)
    local base_exp = defender.drops and defender.drops.exp or 50
    local level_difference = defender.level - attacker.level
    
    -- 根据等级差异调整经验值
    local exp_multiplier = 1.0
    if level_difference > 5 then
        exp_multiplier = 1.5 -- 高等级敌人提供更多经验
    elseif level_difference < -5 then
        exp_multiplier = 0.5 -- 低等级敌人提供较少经验
    end
    
    local exp = base_exp * exp_multiplier
    return math.floor(exp)
end

-- 计算金币奖励
function CombatCalculator:calculate_gold_reward(defender)
    local base_gold = defender.drops and defender.drops.gold or 20
    return base_gold
end

-- 计算物品掉落
function CombatCalculator:calculate_item_drops(defender)
    local drops = {}
    
    if defender.drops and defender.drops.items then
        for _, drop_info in ipairs(defender.drops.items) do
            if Random:bool(drop_info.probability) then
                table.insert(drops, {
                    item_id = drop_info.item_id,
                    quantity = drop_info.quantity or 1
                })
            end
        end
    end
    
    return drops
end

-- 导出模块
return CombatCalculator